//
//  BasicBlock.cpp
//  ConstructGccfg2.0
//
//  Created by Bryce Holton on 12/4/12.
//  Copyright (c) 2012 Bryce Holton. All rights reserved.
//

#include "BasicBlock.h"

BasicBlock::BasicBlock(int id)
{
    this->id = id;
    color = WHITE;
}
BasicBlock::~BasicBlock()
{//
    for (unsigned int i = 0; i < decendantEdges.size(); i++)
    {
        delete decendantEdges[i];
    }
    decendantEdges.clear();
    ancestorEdges.clear();
    code.clear();
}
void BasicBlock::ReplaceChild(BasicBlock &oldChild, BasicBlock &newChild)
{
    oldChild.DeleteAncestorEdge(*this);
    
    int oldDecendantIndex = DeleteDecendantEdge(oldChild);
    Edge<BasicBlock *> *newEdge = new Edge<BasicBlock *>(this, &newChild);
    
    newChild.SetAncestorEdge(*newEdge);
    InsertDecendantEdge(*newEdge, oldDecendantIndex);
}
void BasicBlock::RemoveChild(BasicBlock &child)
{
    child.DeleteAncestorEdge(*this);
    DeleteDecendantEdge(child);
}
bool BasicBlock::FindChild(BasicBlock &child)
{
    if (FindEdgeIndex(child, decendantEdges) > -1)
    {
        return true;
    }
    return false;
}
int BasicBlock::GetId()
{
    return id;
}
Color BasicBlock::GetColor()
{
    return this->color;
}
void BasicBlock::SetColor(Color color)
{
    this->color = color;
}
void BasicBlock::SetDecendantEdge(BasicBlock &decendant)
{
    Edge<BasicBlock *> *newEdge = new Edge<BasicBlock *>(this, &decendant);
    
    decendant.SetAncestorEdge(*newEdge);
    decendantEdges.push_back(newEdge);
}
vector<Edge<BasicBlock *> *> BasicBlock::GetDecendantEdges()
{
    return decendantEdges;
}
int BasicBlock::DeleteDecendantEdge(BasicBlock &decendant)
{
    int deleteIndex = FindEdgeIndex(decendant, decendantEdges);
    Edge<BasicBlock *> *edgeToDelete = decendantEdges[deleteIndex];
    
    decendantEdges.erase(decendantEdges.begin() + deleteIndex);
    delete edgeToDelete;
    
    return deleteIndex;
}
void BasicBlock::InsertDecendantEdge(Edge<BasicBlock *> &decEdge, int index)
{
    decendantEdges.insert(decendantEdges.begin() + index, &decEdge);
}
void BasicBlock::SetAncestorEdge(Edge<BasicBlock *> &edge)
{
    ancestorEdges.push_back(&edge);
}
vector<Edge<BasicBlock *> *> BasicBlock::GetAncestorEdges()
{
    return ancestorEdges;
}
int BasicBlock::DeleteAncestorEdge(BasicBlock &ancestor)
{
    int deleteIndex = FindEdgeIndex(ancestor, ancestorEdges);
    
    ancestorEdges.erase(ancestorEdges.begin() + deleteIndex);
    
    return deleteIndex;
}
void BasicBlock::InsertAncestorEdge(Edge<BasicBlock *> &ancEdge, int index)
{
    ancestorEdges.insert(ancestorEdges.begin() + index, &ancEdge);
}
void BasicBlock::SetLineOfCode(string lineOfCode)
{
    code.push_back(lineOfCode);
}
vector<string> BasicBlock::GetCode()
{
    return code;
}
bool BasicBlock::FindFunctionInCode(string &functionName)
{
    bool foundFunction = false;
    
    for (unsigned int i = 0; i < code.size() && !foundFunction; i++)
    {
        if (code[i].find(functionName) != string::npos)
        {
            foundFunction = true;
        }
    }
    
    return foundFunction;
}
int BasicBlock::FindEdgeIndex(BasicBlock &bb, vector<Edge<BasicBlock *> *> &edgeSet)
{
    int edgeIndex = -1;

    for (unsigned int i = 0; i < edgeSet.size() && edgeIndex == -1; i++)
    {        
        if (edgeSet[i]->GetDecendant() == &bb || edgeSet[i]->GetAncestor() == &bb)
        {
            edgeIndex = i;
        }
    }
    
    return edgeIndex;
}
void BasicBlock::Print()
{
    cout << "Basic Block ID: " << GetId() << ", Color: ";
    switch (GetColor())
    {
        case WHITE:
            cout << "White";
            break;
        case GREY:
            cout << "Grey";
            break;
        case BLACK:
            cout << "Black";
            break;
        default:
            break;
    }
    cout << ", Code: " << endl;
    
    vector<string> blockCode = GetCode();
    
    for (unsigned int i = 0; i < blockCode.size(); i++)
    {
        cout << blockCode[i] << endl;
    }
}
